#include <stdio.h>
#include <string.h>
#include <GL/glut.h>
//#include <windows.h>
#include <stack>
#include <queue>
#define WINDOW_HEIGHT 400
#define MAXN 100
typedef unsigned long       COLORREF;
typedef unsigned char       BYTE;
typedef unsigned short      WORD;
typedef unsigned long       DWORD;
#define RGB(r,g,b)          ((COLORREF)(((BYTE)(r)|((WORD)((BYTE)(g))<<8))|(((DWORD)(BYTE)(b))<<16)))

using namespace std;

struct dcpt {
	int x, y;
};

typedef dcpt Direction;

Direction dir[] = {
	{0, -1},
	{1,  0},
	{0,  1},
	{-1, 0}
};

void Boundaryfill(int seedx, int seedy) {
	queue<dcpt> stk1;
	long color = RGB(255, 0, 0); // Filled Color
	long boundary_color = RGB(255, 255, 255); // Boundary Color
	unsigned char params[3];
	

	long borderColor = boundary_color;
	long fillColor = color;
	
	dcpt p1;
	p1.x = seedx;
	p1.y = seedy;

	// Begin to Fill
	stk1.push(p1);

	while(!stk1.empty()) {
		dcpt temp = stk1.front();
		stk1.pop();

		glBegin(GL_POINTS);
			glVertex2i(temp.x, temp.y);
		glEnd();

		/*glReadPixels(temp.x, temp.y, 1, 1, GL_RGB, GL_UNSIGNED_BYTE, params);
		long interiorColor = RGB(params[0], params[1], params[2]);*/

		for(int i=0; i<4; i++) {
			dcpt now;
			now.x = temp.x+dir[i].x;
			now.y = temp.y+dir[i].y;

			glReadPixels(now.x, now.y, 1, 1, GL_RGB, GL_UNSIGNED_BYTE, params);
			long interiorColor = RGB(params[0], params[1], params[2]);

			if((interiorColor != borderColor) && (interiorColor != fillColor)) {
				stk1.push(now);
			}
		}
	}
}

void MyPolygonFill(int n, dcpt * vertices) {	
	int max = vertices[0].x;
	int mix = vertices[0].x;
	int may = vertices[0].y;
	int miy = vertices[0].y;

	glColor3f(1.0, 1.0, 1.0);
	glBegin(GL_LINE_LOOP);
		for(int i=0; i<n; i++) {
			glVertex2i(vertices[i].x, vertices[i].y);
			if(vertices[i].x > max)
				max = vertices[i].x;
			if(vertices[i].x < mix)
				mix = vertices[i].x;
			if(vertices[i].y > may)
				may = vertices[i].y;
			if(vertices[i].y < miy)
				miy = vertices[i].y;
		}
	glEnd();

	int sx = (max+mix)/2;
	int sy = (may+miy)/2;

	glColor3f(1.0, 0.0, 0.0);
	Boundaryfill(sx, sy);
}

void Init(void) {
	glClearColor(0.0, 0.0, 0.0, 0.0);
	glPixelStorei(GL_PACK_ALIGNMENT, 1);
}

void display(void) {
	static dcpt v[4];
	v[0].x = 260, v[0].y = 150;
	v[1].x = 281, v[1].y = 200;
	v[2].x = 340, v[2].y = 230;
	v[3].x = 370, v[3].y = 150;

	glClear(GL_COLOR_BUFFER_BIT);

	MyPolygonFill(4, v);

	glFlush();
}

void reshape(int w, int h) {
	glViewport(0, 0, w, h);
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	gluOrtho2D(0, w, 0, h);
}

void keyboard(unsigned char key, int x, int y) {
	switch(key) {
		case 27: exit(0);
	}
}

int main(int argc, char * argv[]) {
	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE);
	glutInitWindowPosition(50, 100);
	glutInitWindowSize(650, 400);
	glutCreateWindow("Polygon Fill");

	Init();

	glutDisplayFunc(display);
	glutReshapeFunc(reshape);
	glutKeyboardFunc(keyboard);
	
	glutMainLoop();
	
	return 0;
}
